package top.dotgo.service.base;

import com.querydsl.core.Tuple;
import com.querydsl.core.types.Expression;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Path;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQuery;
import top.dotgo.dao.base.BaseDao;
import top.dotgo.kit.bean.Page;
import top.dotgo.model.BaseQuery;
import top.dotgo.model.IBaseDTO;
import top.dotgo.model.IBaseEntity;
import top.dotgo.model.IBaseMapping;

import java.io.Serializable;
import java.util.List;
import java.util.function.Function;

/**
 * @author : lin
 * @date : 2019/10/11 18:36
 */
public interface IBaseService<T extends IBaseEntity, D extends IBaseDTO<T>, P> {

    /**
     * 新增
     *
     * @param obj obj
     * @return D extends IBaseDTO<T>
     */
    D save(D obj);

    /**
     * 新增 批量
     *
     * @param list list
     * @return List<D extends IBaseDTO < T>>
     */
    List<D> save(List<D> list);

    /**
     * 新增 并刷新缓存
     *
     * @param obj obj
     * @return D
     */
    D saveAndFlush(D obj);

    /**
     * 根据id  更新字段  默认忽略所有null值
     *
     * @param obj obj
     */
    void updateById(D obj);

    /**
     * 根据id  更新字段
     *
     * @param obj            obj
     * @param nullProperties 将哪些字段设置成null
     * @return obj  null 代表修改失败
     */
    D updateById(D obj, Path<?>... nullProperties);

    /**
     * 根据where条件 更新 对象
     *
     * @param obj        obj
     * @param predicates where条件 支持复杂嵌套
     * @return long 受影响行数
     */
    long updateByWhere(D obj, Predicate... predicates);

    /**
     * 根据where条件 更新 对象
     *
     * @param obj            obj
     * @param nullProperties 将哪些字段设置成null
     * @param predicates     where条件 支持复杂嵌套
     * @return long 受影响行数
     */
    long updateByWhere(D obj, List<Path<?>> nullProperties, Predicate... predicates);

    /**
     * 根据主键删除
     *
     * @param id id
     */
    void delete(Serializable id);

    /**
     * 根据主键删除
     *
     * @param ids ids
     * @return long 受影响行数
     */
    long delete(List<P> ids);

    /**
     * 根据 实体对象值 批量删除
     *
     * @param obj obj
     * @return long 受影响行数
     */
    long delete(D obj);

    /**
     * 根据where条件 删除 对象
     *
     * @param predicates where条件 支持复杂嵌套
     * @return long 受影响行数
     */
    long delete(Predicate... predicates);

    /**
     * 查询数量
     *
     * @param id 主键
     * @return long数量
     */
    long count(Serializable id);

    /**
     * 查询数量
     *
     * @param obj 对象值
     * @return long数量
     */
    long count(D obj);

    /***
     * 查询数量
     * @param predicates  where条件 支持复杂嵌套
     * @return long数量
     */
    long count(Predicate... predicates);

    /***
     * 根据id查找
     * @param id id
     * @return D
     */
    D find(Serializable id);

    /**
     * 根据id查找指定字段
     *
     * @param id    id
     * @param paths paths
     * @return D
     */
    D find(Serializable id, Path<?>... paths);

    /**
     * 根据id 查找指定字段
     *
     * @param id         id
     * @param expression expression
     * @return D
     */
    D find(Serializable id, Expression<T> expression);

    /**
     * 查找第一个
     *
     * @param obj    obj
     * @param orders 排序
     * @return D
     */
    D findFirst(D obj, OrderSpecifier<?>... orders);

    /**
     * 查找第一个
     *
     * @param obj    obj
     * @param paths  指定字段
     * @param orders 排序
     * @return D
     */
    D findFirst(D obj, List<Path<?>> paths, OrderSpecifier<?>... orders);

    /**
     * 条件查询第一个
     *
     * @param orders     orders
     * @param predicates predicates
     * @return D
     */
    D findFirst(List<Predicate> predicates, OrderSpecifier<?>... orders);

    /**
     * 条件查询第一个 指定字段
     *
     * @param paths      paths
     * @param predicates predicates
     * @param orders     orders
     * @return D
     */
    D findFirst(List<Path<?>> paths, List<Predicate> predicates, OrderSpecifier<?>... orders);

    /**
     * 条件查询第一个 指定字段
     *
     * @param expression expression
     * @param predicates predicates
     * @param orders     orders
     * @return D
     */
    D findFirst(Expression<T> expression, List<Predicate> predicates, OrderSpecifier<?>... orders);

    /**
     * 根据id 查询所有
     *
     * @param ids ids
     * @return List<D>
     */
    List<D> findList(List<P> ids);

    /**
     * 根据 queryBean 查询
     *
     * @param queryBean queryBean
     * @return List<D>
     */
    List<D> findList(BaseQuery<T> queryBean);

    /***
     * 查询全部
     * @param orders 排序
     * @return List<D>
     */
    List<D> findList(OrderSpecifier<?>... orders);

    /**
     * 根据 queryBean 查询
     *
     * @param query     JPAQuery<Tuple>
     * @param queryBean queryBean
     * @param convert   Function<Tuple, D>
     * @return Page<E>
     */
    Page<D> findList(JPAQuery<Tuple> query, BaseQuery<T> queryBean, Function<Tuple, D> convert);

    /**
     * 条件查询
     *
     * @param query      query
     * @param predicates predicates
     * @param convert    convert
     * @param orders     orders
     * @return Page<E>
     */
    Page<D> findList(JPAQuery<Tuple> query, List<Predicate> predicates, Function<Tuple, D> convert, OrderSpecifier<?>... orders);

    /**
     * 根据对象值 查找
     *
     * @param obj    obj
     * @param orders 排序
     * @return List<D>
     */
    List<D> findList(D obj, OrderSpecifier<?>... orders);

    /**
     * 条件查询
     *
     * @param orders     orders
     * @param predicates predicates
     * @return List<D>
     */
    List<D> findList(List<Predicate> predicates, OrderSpecifier<?>... orders);

    /***
     * 根据条件查询 指定字段
     * @param expression  Projections.fields
     * @param orders orders
     * @param predicates predicates
     * @return List<D>
     */
    List<D> findList(Expression<T> expression, List<Predicate> predicates, OrderSpecifier<?>... orders);

    /**
     * 根据条件查询 指定字段
     *
     * @param paths      paths
     * @param orders     orders
     * @param predicates predicates
     * @return List<D>
     */
    List<D> findList(List<Path<?>> paths, List<Predicate> predicates, OrderSpecifier<?>... orders);

    /**
     * 分页查找全部
     *
     * @param page page
     * @param size size
     * @return Page<D>
     */
    Page<D> findPage(int page, int size);

    /**
     * 根据 queryBean 分页查询
     *
     * @param queryBean queryBean
     * @return Page<D>
     */
    Page<D> findPage(BaseQuery<T> queryBean);

    /**
     * 根据 queryBean 分页查询
     *
     * @param query     JPAQuery<Tuple>
     * @param queryBean queryBean
     * @param convert   Function<Tuple, D>
     * @return Page<D>
     */
    Page<D> findPage(JPAQuery<Tuple> query, BaseQuery<T> queryBean, Function<Tuple, D> convert);

    /**
     * 条件查询 分页
     *
     * @param query      JPAQuery<Tuple>
     * @param predicates predicates
     * @param page       page
     * @param size       size
     * @param convert    Function<Tuple, D>
     * @param orders     orders
     * @return Page<D>
     */
    Page<D> findPage(JPAQuery<Tuple> query, List<Predicate> predicates, int page, int size, Function<Tuple, D> convert, OrderSpecifier<?>... orders);

    /**
     * 根据对象值 分页查询
     *
     * @param obj    obj
     * @param page   page
     * @param size   size
     * @param orders 排序
     * @return Page<D>
     */
    Page<D> findPage(D obj, int page, int size, OrderSpecifier<?>... orders);

    /**
     * 条件查询 分页
     *
     * @param orders     orders
     * @param page       page
     * @param size       size
     * @param predicates predicates
     * @return Page<D>
     */
    Page<D> findPage(List<Predicate> predicates, int page, int size, OrderSpecifier<?>... orders);

    /***
     * 根据条件查询 指定字段  分页
     * @param paths paths
     * @param orders orders
     * @param page page
     * @param size size
     * @param predicates predicates
     * @return Page<D>
     */
    Page<D> findPage(List<Path<?>> paths, List<Predicate> predicates, int page, int size, OrderSpecifier<?>... orders);

    /***
     * 根据条件查询 指定字段  分页
     * @param expression Projections.fields
     * @param orders orders
     * @param page page
     * @param size size
     * @param predicates predicates
     * @return Page<D>
     */
    Page<D> findPage(Expression<T> expression, List<Predicate> predicates, int page, int size, OrderSpecifier<?>... orders);

    /**
     * 刷新缓存
     */
    void flush();

//    /**
//     * 获得查询工厂
//     *
//     * @return JPAQueryFactory
//     */
//    JPAQueryFactory getFactory();

    /**
     * 获得原始 BaseDao
     *
     * @return BaseDao<D, P>
     */
    BaseDao<T, P> getBaseDao();

}
